// package proto 提供 Protobuf 格式的序列化与反序列化功能
// 基于 google.golang.org/protobuf/proto 库实现，仅支持实现 proto.Message 接口的类型
package proto

import (
	"errors"

	"google.golang.org/protobuf/proto" // 依赖官方 Protobuf 库，提供核心编解码能力
)

// Name 编解码器标识名称，固定为 "proto"
const Name = "proto"

// DefaultCodec 是默认的 Protobuf 编解码器实例，提供便捷的编解码入口
var DefaultCodec = &codec{}

// codec 实现 Protobuf 编解码功能的结构体
// 无内部状态，线程安全，通过方法封装 Protobuf 库的编解码逻辑
type codec struct{}

// Name 返回编解码器的标识名称
func (codec) Name() string {
	return Name
}

// Marshal 对实现 proto.Message 接口的类型进行 Protobuf 序列化（编码）
// 参数：
//
//	v - 必须是实现 proto.Message 接口的实例（如 Protobuf 生成的结构体），否则返回错误
//
// 返回值：
//
//	[]byte - 序列化后的 Protobuf 二进制数据
//	error - 若 v 未实现 proto.Message，返回 "can't marshal a value that not implements proto.Buffer interface" 错误；
//	        其他错误为 proto.Marshal 内部产生（如数据不合法）
func (codec) Marshal(v interface{}) ([]byte, error) {
	// 类型断言：检查 v 是否实现 proto.Message 接口
	msg, ok := v.(proto.Message)
	if !ok {
		return nil, errors.New("can't marshal a value that not implements proto.Buffer interface")
	}

	// 调用官方库进行序列化
	return proto.Marshal(msg)
}

// Unmarshal 将 Protobuf 二进制数据反序列化为实现 proto.Message 接口的类型（解码）
// 参数：
//
//	data - 待反序列化的 Protobuf 二进制数据
//	v - 必须是实现 proto.Message 接口的类型指针（如 &pb.User{}），否则返回错误
//
// 返回值：
//
//	error - 若 v 未实现 proto.Message，返回 "can't unmarshal to a value that not implements proto.Buffer" 错误；
//	        其他错误为 proto.Unmarshal 内部产生（如数据格式错误、类型不匹配）
func (codec) Unmarshal(data []byte, v interface{}) error {
	// 类型断言：检查 v 是否实现 proto.Message 接口
	msg, ok := v.(proto.Message)
	if !ok {
		return errors.New("can't unmarshal to a value that not implements proto.Buffer")
	}

	// 调用官方库进行反序列化
	return proto.Unmarshal(data, msg)
}

// Marshal 包级 Protobuf 序列化函数，基于 DefaultCodec 实现
// 功能与 codec.Marshal 一致，提供更简洁的调用方式
func Marshal(v interface{}) ([]byte, error) {
	return DefaultCodec.Marshal(v)
}

// Unmarshal 包级 Protobuf 反序列化函数，基于 DefaultCodec 实现
// 功能与 codec.Unmarshal 一致，提供更简洁的调用方式
func Unmarshal(data []byte, v interface{}) error {
	return DefaultCodec.Unmarshal(data, v)
}
